/*
 * graph2D
 * Copyright (c) 2009 Shun Moriya <shun@mnu.sakura.ne.jp>
 *
 * The MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#define INCLUDE_FROM_OBJC_C
#include "data_impl.h"

@implementation DataController

/*!
 * ドキュメントパスを取得します
 */
+(NSString*)getDocumentPath
{
	NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	return [paths objectAtIndex:0];
}

/*!
 * ドキュメントパスを取得します
 */
+(NSString*)getDocumentPathWithString:(NSString*)filename
{
	NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	return [[paths objectAtIndex:0] stringByAppendingPathComponent:filename];
}

/*!
 * リソースパスを取得します
 */
+(NSString*)getResoucePath
{
	return [[NSBundle mainBundle] resourcePath];
}

/*!
 * リソースパスを取得します
 */
+(NSString*)getResoucePathWithString:(NSString*)filename
{
	NSString* bundlePath = [[NSBundle mainBundle] resourcePath];
	return [bundlePath stringByAppendingPathComponent:filename];
}

/*!
 * リソースパスをURI形式で取得します
 */
+(NSURL*)getResouceUriWithString:(NSString*)filename
{
	return [NSURL fileURLWithPath:[DataController getResoucePathWithString:filename]];
}

/*!
 * ファイルが存在するか調べます
 */
+(BOOL)fileExistsAtPath:(NSString*)path
{
	return [[NSFileManager defaultManager] fileExistsAtPath:path];
}

@end

////////////////////////////////////////////////////////////////////////////////
#include "../../abort.h"

namespace Graph2D
{
	namespace Implementation
	{
		namespace Data
		{
			/*!
			 * ドキュメントパスを取得します
			 */
			const char* getDocumentPath()
			{
				return [[DataController getDocumentPath] UTF8String];
			}

			/*!
			 * リソースパスを取得します
			 */
			const char* getResoucePath()
			{
				return [[DataController getResoucePath] UTF8String];
			}

			/*!
			 * ファイルの存在を確認します
			 */
			bool exist(const std::string& filename, const bool resource)
			{
				NSString* name = [NSString stringWithUTF8String:filename.c_str()];

				NSString* path = resource ?
					[DataController getResoucePathWithString:name] :
					[DataController getDocumentPathWithString:name] ;

				return [[NSFileManager defaultManager] fileExistsAtPath:path] ? true : false;
			}

			/*!
			 * インスタンスを作成してデータを読み込みます
			 */
			void* create(const void* buffer, const size_t size)
			{
				NSData* data = [[NSData alloc] initWithBytes:buffer length:size];

				return reinterpret_cast<void*>(data);
			}

			/*!
			 * インスタンスを作成してファイルを読み込みます
			 */
			void* create(const std::string& filename, const bool resource)
			{
				NSString* name = [NSString stringWithUTF8String:filename.c_str()];

				NSString* path = resource ?
					[DataController getResoucePathWithString:name] :
					[DataController getDocumentPathWithString:name] ;

				NSData* data = [[NSData alloc] initWithContentsOfFile:path];

				return reinterpret_cast<void*>(data);
			}

			/*!
			 * インスタンスを解放します
			 */
			void release(void* self)
			{
				if(self)
				{
					NSData* data = reinterpret_cast<NSData*>(self);
					[data release];
				}
			}

			/*!
			 * データをファイルに保存します
			 */
			bool write(void* self, const std::string& filename)
			{
				NSString* name = [NSString stringWithUTF8String:filename.c_str()];

				NSString* path = [DataController getDocumentPathWithString:name];

				NSData* data = reinterpret_cast<NSData*>(self);
				return [data writeToFile:path atomically:YES];
			}

			/*!
			 * データの先頭アドレスを取得します
			 */
			const void* getBuffer(void* self)
			{
				NSData* data = reinterpret_cast<NSData*>(self);
				return [data bytes];
			}

			/*!
			 * データのサイズを取得します
			 */
			size_t getSize(void* self)
			{
				NSData* data = reinterpret_cast<NSData*>(self);
				return [data length];
			}
		}
	}
}
